home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / tsipp / tsipp.lha / tsipp3.0a / src / tSippBezier.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-02  |  18.6 KB  |  552 lines

  1. /*
  2.  *=============================================================================
  3.  *                                  tSippBezier.c
  4.  *-----------------------------------------------------------------------------
  5.  * Tcl commands to create Bezier defined SIPP objects. 
  6.  *-----------------------------------------------------------------------------
  7.  * Copyright 1992 Mark Diekhans
  8.  * Permission to use, copy, modify, and distribute this software and its
  9.  * documentation for any purpose and without fee is hereby granted, provided
  10.  * that the above copyright notice appear in all copies.  Mark Diekhans makes
  11.  * no representations about the suitability of this software for any purpose.
  12.  * It is provided "as is" without express or implied warranty.
  13.  *-----------------------------------------------------------------------------
  14.  * $Id: tSippBezier.c,v 2.0 1992/11/02 03:56:17 markd Rel $
  15.  *=============================================================================
  16.  */
  17.  
  18. #include "tSippInt.h"
  19.  
  20. /*
  21.  * Type used in parsing the parameters for the Bezier commands.
  22.  */
  23. typedef struct {
  24.     tSippGlob_pt    tSippGlobPtr;
  25.     Tcl_Interp     *interp;
  26.     int             texture;
  27.     Shader         *shaderPtr;
  28.     void           *surfDescPtr;
  29.     unsigned        resolution;
  30.     int             numVertices;
  31.     Vector         *vertices;
  32. } bezierGlob_t, *bezierGlob_pt;
  33.  
  34. /*
  35.  * Textures that are invalid for Bezier defined objects.
  36.  */
  37. static int invalidTextureMappings [3] = {
  38.     SPHERICAL,
  39.     CYLINDRICAL,
  40.     -1};
  41.  
  42.  
  43. /*
  44.  * Internal prototypes.
  45.  */
  46. static bool
  47. ConvertBezierVertices  _ANSI_ARGS_((bezierGlob_pt  bezierGlobPtr,
  48.                                     char          *listStr));
  49.  
  50. static bool
  51. ConvertCurveIndexList  _ANSI_ARGS_((bezierGlob_pt  bezierGlobPtr,
  52.                                     char          *listStr,
  53.                                     int            indices []));
  54.  
  55. static bool
  56. ConvertCurveIndexMatrix  _ANSI_ARGS_((bezierGlob_pt  bezierGlobPtr,
  57.                                       char         *listStr,
  58.                                       int           indices []));
  59.  
  60. static bool
  61. ConvertBezierCurveIndices  _ANSI_ARGS_((bezierGlob_pt    bezierGlobPtr,
  62.                                         char            *listStr,
  63.                                         int             *numCurvesPtr,
  64.                                         int            **indicesPtr));
  65.  
  66. static bool
  67. ConvertBezierPatchIndices  _ANSI_ARGS_((bezierGlob_pt    bezierGlobPtr,
  68.                                         char            *listStr,
  69.                                         int             *numPatchesPtr,
  70.                                         int            **indicesPtr));
  71.  
  72. static bool
  73. SetupBezierCmd _ANSI_ARGS_((tSippGlob_pt     tSippGlobPtr,
  74.                             int              argc,
  75.                             char           **argv,
  76.                             char            *vertexIndexTitle,
  77.                             bezierGlob_pt   bezierGlobPtr));
  78.  
  79. /*=============================================================================
  80.  * ConvertBezierVertices --
  81.  *   Convert a list of vertices and added them to a Bezier object structure.
  82.  *
  83.  * Parameters:
  84.  *   o bezierGlobPtr (I/O) - Globals for Bezier setup.
  85.  *   o listStr (I) - Tcl list containing the vertices to convert.
  86.  * Returns:
  87.  *   TRUE if the list and numbers are valid, FALSE if there is an error.
  88.  *-----------------------------------------------------------------------------
  89.  */
  90. static bool
  91. ConvertBezierVertices (bezierGlobPtr, listStr)
  92.     bezierGlob_pt  bezierGlobPtr;
  93.     char          *listStr;
  94. {
  95.     int      vertArgc, idx;
  96.     char   **vertArgv;
  97.     Vector  *vertices;    
  98.  
  99.     if (Tcl_SplitList (bezierGlobPtr->interp, listStr, &vertArgc,
  100.                        &vertArgv) != TCL_OK)
  101.         return FALSE;
  102.     vertices = (Vector *) malloc (vertArgc * sizeof (Vector));
  103.  
  104.     for (idx = 0; idx < vertArgc; idx++) {
  105.         if (!TSippConvertVertex (bezierGlobPtr->tSippGlobPtr, vertArgv [idx], 
  106.                                 &vertices [idx]))
  107.             goto errorCleanup;
  108.     }
  109.     bezierGlobPtr->numVertices = vertArgc;
  110.     bezierGlobPtr->vertices = vertices;
  111.     ckfree (vertArgv);
  112.     return TRUE;
  113.     
  114. errorCleanup:
  115.     free (vertices);
  116.     ckfree (vertArgv);
  117.     return FALSE;
  118.  
  119. } /* ConvertBezierVertices */
  120.  
  121. /*=============================================================================
  122.  * ConvertCurveIndexList --
  123.  *   Convert a single list of 4 vertices indices.
  124.  *
  125.  * Parameters:
  126.  *   o bezierGlobPtr (I/O) - Globals for Bezier setup.
  127.  *   o listStr (I) - Tcl list containing the vertices to convert.
  128.  *   o indices (O) - An array to return the indices in.
  129.  * Returns:
  130.  *   TRUE if the list and numbers are valid, FALSE if there is an error.
  131.  *-----------------------------------------------------------------------------
  132.  */
  133. static bool
  134. ConvertCurveIndexList (bezierGlobPtr, listStr, indices)
  135.     bezierGlob_pt  bezierGlobPtr;
  136.     char          *listStr;
  137.     int            indices [];
  138. {
  139.     int         vertArgc, idx;
  140.     char      **vertArgv;
  141.     unsigned    vertIndex;
  142.     
  143.     if (Tcl_SplitList (bezierGlobPtr->interp, listStr, &vertArgc,
  144.                        &vertArgv) != TCL_OK)
  145.         return FALSE;
  146.     if (vertArgc != 4) {
  147.         Tcl_AppendResult (bezierGlobPtr->interp,
  148.                           "list of vertex indices must have 4 indices",
  149.                           (char *) NULL);
  150.         goto errorCleanup;
  151.     }
  152.     for (idx = 0; idx < 4; idx++) {
  153.         if (Tcl_GetUnsigned (bezierGlobPtr->interp, vertArgv [idx],
  154.                              &vertIndex) != TCL_OK)
  155.             goto errorCleanup;
  156.         if (vertIndex >= bezierGlobPtr->numVertices) {
  157.             sprintf (bezierGlobPtr->interp->result,
  158.                      "vertex index %d out of range, expect: 0 .. %d",
  159.                      vertIndex, bezierGlobPtr->numVertices - 1);
  160.             goto errorCleanup;
  161.         }
  162.         indices [idx] = vertIndex;
  163.     }
  164.  
  165.     ckfree (vertArgv);
  166.     return TRUE;
  167.     
  168. errorCleanup:
  169.     ckfree (vertArgv);
  170.     return FALSE;
  171.  
  172. } /* ConvertCurveIndexList */
  173.  
  174. /*=============================================================================
  175.  * ConvertCurveIndexMatrix --
  176.  *   Convert a 4x4 matrix of vertex indices.
  177.  *
  178.  * Parameters:
  179.  *   o bezierGlobPtr (I/O) - Globals for Bezier setup.
  180.  *   o listStr (I) - Tcl list containing the list of vertices to convert.
  181.  *   o indices (O) - An array to return the indices in, they are returned
  182.  *     in 16 sequential cells.
  183.  * Returns:
  184.  *   TRUE if the list and numbers are valid, FALSE if there is an error.
  185.  *-----------------------------------------------------------------------------
  186.  */
  187. static bool
  188. ConvertCurveIndexMatrix (bezierGlobPtr, listStr, indices)
  189.     bezierGlob_pt  bezierGlobPtr;
  190.     char         *listStr;
  191.     int           indices [];
  192. {
  193.     int         matArgc, idx;
  194.     char      **matArgv;
  195.     unsigned    vertIndex;
  196.     
  197.     if (Tcl_SplitList (bezierGlobPtr->interp, listStr, &matArgc,
  198.                        &matArgv) != TCL_OK)
  199.         return FALSE;
  200.     if (matArgc != 4) {
  201.         Tcl_AppendResult (bezierGlobPtr->interp,
  202.                  "matrix of vertex indices must have 4 list of vertex indices",
  203.                  (char *) NULL);
  204.         goto errorCleanup;
  205.     }
  206.     for (idx = 0; idx < 4; idx++) {
  207.         if (!ConvertCurveIndexList (bezierGlobPtr, matArgv [idx],
  208.                                     &indices [idx * 4]))
  209.             goto errorCleanup;
  210.     }
  211.  
  212.     ckfree (matArgv);
  213.     return TRUE;
  214.     
  215. errorCleanup:
  216.     ckfree (matArgv);
  217.     return FALSE;
  218.  
  219. } /* ConvertCurveIndexMatrix */
  220.  
  221. /*=============================================================================
  222.  * ConvertBezierCurveIndices --
  223.  *   Convert a list of vertices indices representing 4 control points and
  224.  * added them to a Bezier object structure.
  225.  *
  226.  * Parameters:
  227.  *   o bezierGlobPtr (I/O) - Globals for Bezier setup.
  228.  *   o listStr (I) - Tcl list containing the vertices to convert.
  229.  *   o numCurvesPtr (O) - The number of curves is returned here.
  230.  *   o indicesPtr (O) - An array is allocated and returned here.  The indices
  231.  *     are returned in sequential cells.
  232.  * Returns:
  233.  *   TRUE if the list and numbers are valid, FALSE if there is an error.
  234.  *-----------------------------------------------------------------------------
  235.  */
  236. static bool
  237. ConvertBezierCurveIndices (bezierGlobPtr, listStr, numCurvesPtr, indicesPtr)
  238.     bezierGlob_pt    bezierGlobPtr;
  239.     char            *listStr;
  240.     int             *numCurvesPtr;
  241.     int            **indicesPtr;
  242. {
  243.     int     curveArgc, idx;
  244.     char  **curveArgv;
  245.     int    *indices;
  246.  
  247.     if (Tcl_SplitList (bezierGlobPtr->interp, listStr, &curveArgc,
  248.                        &curveArgv) != TCL_OK)
  249.         return FALSE;
  250.  
  251.     indices = (int *) malloc (curveArgc * 4 * sizeof (int *));
  252.  
  253.     for (idx = 0; idx < curveArgc; idx++) {
  254.         if (!ConvertCurveIndexList (bezierGlobPtr, curveArgv [idx],
  255.                                     &indices [idx * 4]))
  256.             goto errorCleanup;
  257.     }
  258.     *numCurvesPtr = curveArgc;
  259.     *indicesPtr = indices;
  260.     ckfree (curveArgv);
  261.     return TRUE;
  262.     
  263. errorCleanup:
  264.     free (indices);
  265.     ckfree (curveArgv);
  266.     return FALSE;
  267.  
  268. } /* ConvertBezierCurveIndices */
  269.  
  270. /*=============================================================================
  271.  * ConvertBezierPatchIndices --
  272.  *   Convert a list of vertices indices representing 16 control points and
  273.  * added them to a Bezier object structure.
  274.  *
  275.  * Parameters:
  276.  *   o bezierGlobPtr (I/O) - Globals for Bezier setup.
  277.  *   o listStr (I) - Tcl list containing the vertices to convert.
  278.  *   o numPatchesPtr (O) - The number of curves is returned here.
  279.  *   o indicesPtr (O) - An array is allocated and returned here.  The indices
  280.  *     are returned in sequential cells.
  281.  * Returns:
  282.  *   TRUE if the list and numbers are valid, FALSE if there is an error.
  283.  *-----------------------------------------------------------------------------
  284.  */
  285. static bool
  286. ConvertBezierPatchIndices (bezierGlobPtr, listStr, numPatchesPtr, indicesPtr)
  287.     bezierGlob_pt    bezierGlobPtr;
  288.     char            *listStr;
  289.     int             *numPatchesPtr;
  290.     int            **indicesPtr;
  291. {
  292.     int    patchArgc, idx;
  293.     char **patchArgv;
  294.     int   *indices;
  295.  
  296.     if (Tcl_SplitList (bezierGlobPtr->interp, listStr, &patchArgc,
  297.                        &patchArgv) != TCL_OK)
  298.         return FALSE;
  299.  
  300.     indices = (int *) malloc (patchArgc * 16 * sizeof (int *));
  301.  
  302.     for (idx = 0; idx < patchArgc; idx++) {
  303.         if (!ConvertCurveIndexMatrix (bezierGlobPtr, patchArgv [idx],
  304.                                       &indices [idx * 16]))
  305.             goto errorCleanup;
  306.     }
  307.     *numPatchesPtr = patchArgc;
  308.     *indicesPtr = indices;
  309.     ckfree (patchArgv);
  310.     return TRUE;
  311.     
  312. errorCleanup:
  313.     free (indices);
  314.     ckfree (patchArgv);
  315.     return FALSE;
  316.  
  317. } /* ConvertBezierPatchIndices */
  318.  
  319. /*=============================================================================
  320.  * SetupBezierCmd --
  321.  *   Do setup for the Bezier commands, which are in the form:
  322.  *     SippBezierXXXX resolution vertexlist XXXXlist shaderhandle [texture]
  323.  *   This command handles all parameters except the XXXXlist.
  324.  * Parameters:
  325.  *   o tSippGlobPtr (I) - A pointer to the Tcl SIPP global structure.
  326.  *   o argc, argv (I) - The command argument vector.
  327.  *   o vertexIndexTitle (I) - The string to print out in the error message for
  328.  *     the XXXXlist argument.
  329.  *   o bezierGlobPtr (O) - The parameters the were processed are returned in
  330.  *     this structure.
  331.  * Returns:
  332.  *   TRUE if all is ok, FALSE if an error is detected.
  333.  *-----------------------------------------------------------------------------
  334.  */
  335. static bool
  336. SetupBezierCmd (tSippGlobPtr, argc, argv, vertexIndexTitle, bezierGlobPtr)
  337.     tSippGlob_pt     tSippGlobPtr;
  338.     int              argc;
  339.     char           **argv;
  340.     char            *vertexIndexTitle;
  341.     bezierGlob_pt   bezierGlobPtr;
  342. {
  343.  
  344.     if ((argc < 5) || (argc > 6)) {
  345.         Tcl_AppendResult (tSippGlobPtr->interp, "wrong # args: ", argv [0], 
  346.                           " resolution vertexlist ", vertexIndexTitle,
  347.                           " shaderhandle [texture]", (char *) NULL);
  348.         return FALSE;
  349.     }                     
  350.  
  351.     bezierGlobPtr->tSippGlobPtr = tSippGlobPtr;
  352.     bezierGlobPtr->interp       = tSippGlobPtr->interp;
  353.     bezierGlobPtr->texture      = NATURAL;
  354.  
  355.     if (!TSippConvertPosUnsigned (tSippGlobPtr, argv [1],
  356.                                   &bezierGlobPtr->resolution))
  357.         return FALSE;
  358.  
  359.     if (!ConvertBezierVertices (bezierGlobPtr, argv [2]))
  360.         return FALSE;
  361.  
  362.     bezierGlobPtr->shaderPtr = 
  363.         TSippShaderHandleToPtr (tSippGlobPtr, argv [4],
  364.                                 &bezierGlobPtr->surfDescPtr);
  365.     if (bezierGlobPtr->shaderPtr == NULL)
  366.         return FALSE;
  367.  
  368.     if (argc == 6) {
  369.         if (!TSippParseTextureMapping (tSippGlobPtr, argv [5], 
  370.                                        &bezierGlobPtr->texture,
  371.                                        invalidTextureMappings))
  372.             return FALSE;
  373.     }
  374.  
  375.     return TRUE;
  376.  
  377. } /* SetupBezierCmd */
  378.  
  379. /*=============================================================================
  380.  * SippBezierCurve --
  381.  *   Implements the command:
  382.  *     SippBezierCurve resolution vertexlist curvelist shaderhandle [texture]
  383.  * Note:
  384.  *   This procedure has standard Tcl command calling sematics.  ClientData
  385.  * contains a pointer to the Tcl SIPP global structure.
  386.  *-----------------------------------------------------------------------------
  387.  */
  388. static int
  389. SippBezierCurve (clientData, interp, argc, argv)
  390.     char       *clientData;
  391.     Tcl_Interp *interp;
  392.     int         argc;
  393.     char      **argv;
  394. {
  395.     tSippGlob_pt    tSippGlobPtr = (tSippGlob_pt) clientData;
  396.     bezierGlob_t    bezierGlob;
  397.     int             numCurves;
  398.     int            *indices;
  399.     Object         *objectPtr;
  400.  
  401.     if (!SetupBezierCmd (tSippGlobPtr, argc, argv, "curvelist",
  402.                          &bezierGlob))
  403.         return TCL_ERROR;
  404.  
  405.     if (!ConvertBezierCurveIndices (&bezierGlob, argv [3], &numCurves,
  406.                                     &indices)) {
  407.         free (bezierGlob.vertices);
  408.         return TCL_ERROR;
  409.     }
  410.  
  411.     objectPtr = sipp_bezier_rotcurve (bezierGlob.numVertices, 
  412.                                       bezierGlob.vertices,
  413.                                       numCurves, indices,
  414.                                       bezierGlob.resolution,
  415.                                       bezierGlob.surfDescPtr,
  416.                                       bezierGlob.shaderPtr,
  417.                                       bezierGlob.texture); 
  418.     TSippBindObjectToHandle (tSippGlobPtr,  objectPtr);
  419.  
  420.     free (bezierGlob.vertices);
  421.     free (indices);
  422.     return TCL_OK;
  423.  
  424. } /* SippBezierCurve */
  425.  
  426. /*=============================================================================
  427.  * SippBezierPatch --
  428.  *   Implements the command:
  429.  *     SippBezierPatch resolution vertexlist patchlist shaderhandle [texture]
  430.  * Note:
  431.  *   This procedure has standard Tcl command calling sematics.  ClientData
  432.  * contains a pointer to the Tcl SIPP global structure.
  433.  *-----------------------------------------------------------------------------
  434.  */
  435. static int
  436. SippBezierPatch (clientData, interp, argc, argv)
  437.     char       *clientData;
  438.     Tcl_Interp *interp;
  439.     int         argc;
  440.     char      **argv;
  441. {
  442.     tSippGlob_pt    tSippGlobPtr = (tSippGlob_pt) clientData;
  443.     bezierGlob_t    bezierGlob;
  444.     int             numPatches;
  445.     int            *indices;
  446.     Object         *objectPtr;
  447.  
  448.     if (!SetupBezierCmd (tSippGlobPtr, argc, argv, "patchlist",
  449.                          &bezierGlob))
  450.         return TCL_ERROR;
  451.  
  452.     if (!ConvertBezierPatchIndices (&bezierGlob, argv [3], &numPatches,
  453.                                     &indices)) {
  454.         free (bezierGlob.vertices);
  455.         return TCL_ERROR;
  456.     }
  457.  
  458.     objectPtr = sipp_bezier_patches (bezierGlob.numVertices,
  459.                                      bezierGlob.vertices,
  460.                                      numPatches, indices,
  461.                                      bezierGlob.resolution,
  462.                                      bezierGlob.surfDescPtr,
  463.                                      bezierGlob.shaderPtr,
  464.                                      bezierGlob.texture); 
  465.     TSippBindObjectToHandle (tSippGlobPtr,  objectPtr);
  466.    
  467.     free (bezierGlob.vertices);
  468.     free (indices);
  469.     return TCL_OK;
  470.  
  471. } /* SippBezierPatch */
  472.  
  473. /*=============================================================================
  474.  * SippBezierFile --
  475.  *   Implements the command:
  476.  *      SippBezierFile fileid resolution shaderhandle [texture]
  477.  * Note:
  478.  *   This procedure has standard Tcl command calling sematics.  ClientData
  479.  * contains a pointer to the Tcl SIPP global structure.
  480.  *-----------------------------------------------------------------------------
  481.  */
  482. int
  483. SippBezierFile (clientData, interp, argc, argv)
  484.     char       *clientData;
  485.     Tcl_Interp *interp;
  486.     int         argc;
  487.     char      **argv;
  488. {
  489.     tSippGlob_pt   tSippGlobPtr = (tSippGlob_pt) clientData;
  490.     Shader        *shaderPtr;
  491.     void          *surfDescPtr;
  492.     int            resolution, texture = NATURAL;
  493.     OpenFile      *filePtr;
  494.  
  495.     if ((argc < 4) || (argc > 5)) {
  496.         Tcl_AppendResult (interp, "wrong # args: ", argv [0],
  497.                           " fileid resolution shaderhandle [texture]",
  498.                           (char *) NULL);
  499.         return TCL_ERROR;
  500.     }
  501.  
  502.     if (TclGetOpenFile (interp, argv [1], &filePtr) != TCL_OK)
  503.         return TCL_ERROR;
  504.  
  505.     if (!TSippConvertPosUnsigned (tSippGlobPtr, argv [2], &resolution))
  506.         return TCL_ERROR;
  507.  
  508.     shaderPtr = TSippShaderHandleToPtr (tSippGlobPtr, argv [3],
  509.                                         &surfDescPtr);
  510.     if (shaderPtr == NULL)
  511.         return TCL_ERROR;
  512.  
  513.     if (argc == 5) {
  514.         if (!TSippParseTextureMapping (tSippGlobPtr, argv [4], &texture,
  515.                                        invalidTextureMappings))
  516.             return TCL_ERROR;
  517.     }
  518.  
  519.     TSippBindObjectToHandle (tSippGlobPtr, 
  520.                              sipp_bezier_file (filePtr->f, resolution,
  521.                                                surfDescPtr, shaderPtr,
  522.                                                texture));
  523.  
  524.     return TCL_OK;
  525.  
  526. } /* SippBezierFile */
  527.  
  528. /*=============================================================================
  529.  * TSippBezierInit --
  530.  *   Initialized the polygon and surface commands, including creating the 
  531.  *   polygon table.
  532.  *
  533.  * Parameters:
  534.  *   o tSippGlobPtr (I) - A pointer to the Tcl SIPP global structure.
  535.  *-----------------------------------------------------------------------------
  536.  */
  537. void
  538. TSippBezierInit (tSippGlobPtr)
  539.     tSippGlob_pt  tSippGlobPtr;
  540. {
  541.     static tSippTclCmdTbl_t cmdTable [] = {
  542.         {"SippBezierCurve",      SippBezierCurve},
  543.         {"SippBezierPatch",      SippBezierPatch},
  544.         {"SippBezierFile",       SippBezierFile},
  545.         {NULL,                   NULL}
  546.     };
  547.  
  548.     TSippInitCmds (tSippGlobPtr, cmdTable);
  549.  
  550. } /* TSippBezierInit */
  551.  
  552.